#include "calculateitem14testjson.h"
#include <stdexcept>

void CalculateItem14TestJson::initTestCase()
{
    qDebug() << "=== 初始化 CalculateItem_14 JSON测试 ===";

    testDataFileBase = getTestDataBasePath();
    testResultFileBase = getTestResultBasePath();

    qDebug() << "测试数据基础路径:" << testDataFileBase;
    qDebug() << "测试结果基础路径:" << testResultFileBase;

    QDir testDataDir(testDataFileBase);
    if (!testDataDir.exists()) {
        qFatal("❌ 测试数据目录不存在: %s", testDataFileBase.toUtf8().constData());
    }

    QDir testResultDir(testResultFileBase);
    if (!testResultDir.exists()) {
        if (testResultDir.mkpath(".")) {
            qDebug() << "✅ 测试结果目录创建成功";
        } else {
            qWarning() << "❌ 测试结果目录创建失败";
        }
    }

    qDebug() << "✅ CalculateItem_14 JSON测试环境初始化完成";
}

QString CalculateItem14TestJson::getTestDataBasePath()
{
    QDir currentDir(QDir::currentPath());
    QDir targetDir = currentDir.filePath("../../../../../test_data");
    QString absolutePath = targetDir.absolutePath() + "/";

    if (targetDir.exists()) {
        qDebug() << "✅ 使用相对路径找到测试数据:" << absolutePath;
        return absolutePath;
    } else {
        qWarning() << "❌ 相对路径找不到测试数据，使用硬编码路径";
        return "D:/Work/algorithm-test/test_data/";
    }
}

QString CalculateItem14TestJson::getTestResultBasePath()
{
    QDir currentDir(QDir::currentPath());
    QDir targetDir = currentDir.filePath("../../../../../test_result");
    QString absolutePath = targetDir.absolutePath() + "/";

    if (targetDir.exists()) {
        qDebug() << "✅ 使用相对路径找到测试结果路径:" << absolutePath;
        return absolutePath;
    } else {
        if (targetDir.mkpath(".")) {
            qDebug() << "✅ 创建测试结果路径:" << absolutePath;
            return absolutePath;
        } else {
            qWarning() << "❌ 无法创建测试结果路径，使用硬编码路径";
            return "D:/Work/algorithm-test/test_result/";
        }
    }
}

QJsonObject CalculateItem14TestJson::readJsonObject(const QString& filePath)
{
    qDebug() << "读取JSON对象文件:" << filePath;

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        QString errorMsg = QString("无法打开文件：%1").arg(filePath);
        qWarning() << errorMsg;
        throw std::runtime_error(errorMsg.toStdString());
    }

    QByteArray data = file.readAll();
    file.close();

    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull()) {
        qWarning() << "JSON解析失败，文件内容:" << QString(data).left(100) << "...";
        throw std::runtime_error("JSON解析失败");
    }

    if (!doc.isObject()) {
        qWarning() << "JSON不是对象格式";
        throw std::runtime_error("JSON不是对象格式");
    }

    return doc.object();
}

QJsonArray CalculateItem14TestJson::readJsonArray(const QString& filePath)
{
    qDebug() << "读取JSON数组文件:" << filePath;

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        QString errorMsg = QString("无法打开文件：%1").arg(filePath);
        qWarning() << errorMsg;
        throw std::runtime_error(errorMsg.toStdString());
    }

    QByteArray data = file.readAll();
    file.close();

    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull()) {
        qWarning() << "JSON解析失败，文件内容:" << QString(data).left(100) << "...";
        throw std::runtime_error("JSON解析失败");
    }

    if (!doc.isArray()) {
        qWarning() << "JSON不是数组格式";
        throw std::runtime_error("JSON不是数组格式");
    }

    return doc.array();
}

void CalculateItem14TestJson::createFileRecursion(const QString& fileName)
{
    QFileInfo fileInfo(fileName);
    QDir dir = fileInfo.absoluteDir();

    if (!dir.exists()) {
        dir.mkpath(".");
    }

    QFile file(fileName);
    if (!file.exists()) {
        file.open(QIODevice::WriteOnly);
        file.close();
    }
}

void CalculateItem14TestJson::loadTestData(const QString& folderPath, CSchProcessPosition& processor)
{
    qDebug() << "加载测试数据:" << folderPath;
    
    try {
        // 1. 加载工位数据 pPositionDtos.json
        QString pPositionDtosPath = folderPath + "pPositionDtos.json";
        QFile pPositionDtosFile(pPositionDtosPath);
        if (pPositionDtosFile.exists()) {
            QJsonObject pPositionDtos = readJsonObject(pPositionDtosPath);
            qDebug() << "加载工位数据数量:" << pPositionDtos.keys().size();
            
            // 初始化PositionManager
            processor.pPositionManager = new CJgPositionManager();
            processor.pPositionManager->mPositions.clear();
            
            // 解析JSON并创建工位对象
            for (auto it = pPositionDtos.begin(); it != pPositionDtos.end(); ++it) {
                QString positionIdStr = it.key();
                int positionId = positionIdStr.toInt();
                QJsonObject positionObj = it.value().toObject();
                
                // 创建工位对象
                CJgPosition* position = new CJgPosition();
                position->miPosNum = positionId;
                position->miWorkerNum = QString::number(positionObj["workerId"].toVariant().toLongLong());
                
                processor.pPositionManager->mPositions.append(position);
            }
        } else {
            qDebug() << "警告：pPositionDtos.json 文件不存在:" << pPositionDtosPath;
            processor.pPositionManager = new CJgPositionManager();
            processor.pPositionManager->mPositions.clear();
        }

        // 2. 加载工人技能数据 workerToTechType.json
        QString workerToTechTypePath = folderPath + "workerToTechType.json";
        QFile workerToTechTypeFile(workerToTechTypePath);
        if (workerToTechTypeFile.exists()) {
            QJsonObject workerToTechType = readJsonObject(workerToTechTypePath);
            qDebug() << "加载工人技能数据数量:" << workerToTechType.keys().size();
            
            // 初始化TechManager
            processor.pTechManger = new CTechManager();
            processor.pTechManger->data.clear();
            
            // 解析JSON并创建工人技能对象
            for (auto it = workerToTechType.begin(); it != workerToTechType.end(); ++it) {
                QString workerKey = it.key();
                QJsonObject workerObj = it.value().toObject();
                QJsonObject valueObj = workerObj["value"].toObject();
                
                QString workerNum = QString::number(workerObj["workerId"].toVariant().toLongLong());
                
                // 创建工人技能对象
                if (!processor.pTechManger->data.contains(workerNum)) {
                    CWorkerTech* workerTech = new CWorkerTech();
                    workerTech->workerNum = workerNum;
                    processor.pTechManger->data.insert(workerNum, workerTech);
                }
                
                // 添加技能类型数据
                QString processType = valueObj["processType"].toString();
                double avgProcessRate = valueObj["avgProcessRate"].toDouble();
                
                CWorkerTech* workerTech = processor.pTechManger->data[workerNum];
                CTech* tech = new CTech();
                tech->fRate = static_cast<float>(avgProcessRate);
                workerTech->TechByType.insert(processType, tech);
            }
        } else {
            qDebug() << "警告：workerToTechType.json 文件不存在:" << workerToTechTypePath;
            processor.pTechManger = new CTechManager();
            processor.pTechManger->data.clear();
        }

        // 3. 加载工序集 hProcessSet.json
        QString hProcessSetPath = folderPath + "hProcessSet.json";
        QFile hProcessSetFile(hProcessSetPath);
        if (hProcessSetFile.exists()) {
            QJsonObject hProcessSet = readJsonObject(hProcessSetPath);
            qDebug() << "加载工序集数量:" << hProcessSet.keys().size();
            qDebug() << "工序集内容预览:" << hProcessSet.keys().first() << "=" << hProcessSet.value(hProcessSet.keys().first()).toObject().value("orderProcessId");
            
            // 清空并设置工序集
            processor.ProcessPosition.hProcessSet.clear();
            // 解析JSON并创建工序对象
            for (auto it = hProcessSet.begin(); it != hProcessSet.end(); ++it) {
                qlonglong processId = it.key().toLongLong();
                QJsonObject processObj = it.value().toObject();
                
                // 创建工序对象
                CJgOrderProcess* process = new CJgOrderProcess();
                process->miProcessId = processObj["orderProcessId"].toVariant().toLongLong();
                process->mProcessCode = processObj["processId"].toString();
                process->mProcessType = processObj["mProcessType"].toString();
                
                // 创建订单对象
                QJsonObject orderObj = processObj["pOrder"].toObject();
                CJgOrder* order = new CJgOrder();
                order->mLocalOrderNum = orderObj["mLocalOrderNum"].toString();
                order->mColor = orderObj["mColor"].toString();
                order->mLineColorNum = orderObj["mLineColorNum"].toString();
                order->mOuterOrderNum = orderObj["mOuterOrderNum"].toString();
                process->pOrder = order;
                
                // 创建调度对象
                process->mScheduling = new CJgProcessSchedule();
                if (processObj.contains("mscheduling") && processObj["mscheduling"].isObject()) {
                    QJsonObject schedulingObj = processObj["mscheduling"].toObject();
                    process->mScheduling->mbHoldFlag = schedulingObj["mbHoldFlag"].toBool();
                    process->mScheduling->mbNGFlag = schedulingObj["mbNGFlag"].toBool();
                    
                    // 设置可执行工位列表
                    if (schedulingObj.contains("mposCanDo") && schedulingObj["mposCanDo"].isArray()) {
                        QJsonArray posCanDoArray = schedulingObj["mposCanDo"].toArray();
                        for (const QJsonValue& value : posCanDoArray) {
                            process->mScheduling->mPosCanDo.append(value.toInt());
                        }
                    }
                } else {
                    qDebug() << "工序" << processId << "缺少mscheduling对象或不是对象类型";
                    qDebug() << "processObj keys:" << processObj.keys();
                }
                
                processor.ProcessPosition.hProcessSet.insert(processId, process);
            }
        } else {
            qDebug() << "警告：hProcessSet.json 文件不存在:" << hProcessSetPath;
            processor.ProcessPosition.hProcessSet.clear();
        }
        
        // 4. 加载可排产的工位 sPositionsScore.json
        QString sPositionsScorePath = folderPath + "sPositionsScore.json";
        QFile sPositionsScoreFile(sPositionsScorePath);
        if (sPositionsScoreFile.exists()) {
            QJsonArray sPositionsScore = readJsonArray(sPositionsScorePath);
            qDebug() << "加载可排产工位数量:" << sPositionsScore.size();
            qDebug() << "可排产工位预览:" << sPositionsScore.first() << "," << sPositionsScore.last();
            
            // 清空并设置可排产工位
            processor.ProcessPosition.sPositionsScore.clear();
            for (const QJsonValue& value : sPositionsScore) {
                processor.ProcessPosition.sPositionsScore.insert(value.toInt());
            }
        } else {
            qDebug() << "警告：sPositionsScore.json 文件不存在:" << sPositionsScorePath;
            processor.ProcessPosition.sPositionsScore.clear();
        }
        
        // 5. 加载按工序查找的分数表 hScoreByProcess.json
        QString hScoreByProcessPath = folderPath + "hScoreByProcess.json";
        QFile hScoreByProcessFile(hScoreByProcessPath);
        if (hScoreByProcessFile.exists()) {
            QJsonObject hScoreByProcess = readJsonObject(hScoreByProcessPath);
            qDebug() << "加载分数表工序数量:" << hScoreByProcess.keys().size();
            qDebug() << "分数表工序预览:" << hScoreByProcess.keys().first();
            
            // 清空并设置分数表
            processor.ProcessPosition.hScoreByProcess.clear();
            // 解析JSON并创建分数对象
            for (auto it = hScoreByProcess.begin(); it != hScoreByProcess.end(); ++it) {
                qlonglong processId = it.key().toLongLong();
                QJsonArray scoresArray = it.value().toArray();
                
                QVector<SSCORE*> scores;
                for (int i = 0; i < scoresArray.size(); ++i) {
                    QJsonObject scoreObj = scoresArray[i].toObject();
                    SSCORE* score = new SSCORE();
                    score->ProcessID = processId;
                    score->Position = scoreObj["positionId"].toInt();
                    score->Total = scoreObj["total"].toDouble();
                    
                    // 初始化分数项数组
                    for (int j = 0; j < _MAX_SCORE_ITEM_; ++j) {
                        score->ScoreItem[j] = 0.0;
                    }
                    
                    // 读取分数项数组
                    QJsonArray scoreItemsArray = scoreObj["scoreItem"].toArray();
                    for (int j = 0; j < qMin(scoreItemsArray.size(), _MAX_SCORE_ITEM_); ++j) {
                        score->ScoreItem[j] = scoreItemsArray[j].toDouble();
                    }
                    
                    // 关联工序对象
                    if (processor.ProcessPosition.hProcessSet.contains(processId)) {
                        score->pOp = processor.ProcessPosition.hProcessSet[processId];
                    }
                    
                    scores.append(score);
                }
                
                processor.ProcessPosition.hScoreByProcess.insert(processId, scores);
            }
        } else {
            qDebug() << "警告：hScoreByProcess.json 文件不存在:" << hScoreByProcessPath;
            processor.ProcessPosition.hScoreByProcess.clear();
        }
        
        // 建立工序和工位之间的关联
        for (auto it = processor.ProcessPosition.hProcessSet.begin(); 
             it != processor.ProcessPosition.hProcessSet.end(); ++it) {
            CJgOrderProcess* process = it.value();
            // 为每个工序添加所有可排产的工位到可执行工位列表中
            for (int position : processor.ProcessPosition.sPositionsScore) {
                process->mScheduling->mPosCanDo.append(position);
            }
        }
        
        // 初始化PreScheduling
        processor.preScheduling = new CPreScheduling();
        processor.preScheduling->processPos = &processor;
        processor.preScheduling->pOrderManager = new COrderManager();
        processor.preScheduling->pSchData = processor.pSchData;
        
    } catch (const std::exception& e) {
        qWarning() << "加载测试数据失败:" << e.what();
        throw;
    }
}

void CalculateItem14TestJson::testSingleCase(const QString& folderPath, const QString& resultFileName)
{
    qDebug() << "测试用例路径:" << folderPath;

    try {
        // 1. 创建 CSchProcessPosition 实例
        CSchProcessPosition schProcessPosition;
        
        // 2. 加载测试数据
        loadTestData(folderPath, schProcessPosition);
        
        // 3. 读取函数参数
        double ratio = 0.0;
        QString testCasesPath = folderPath + "testCases.json";
        QFile testCasesFile(testCasesPath);
        if (testCasesFile.exists()) {
            QJsonObject functionParams = readJsonObject(testCasesPath);
            ratio = functionParams["ratio"].toDouble();
            qDebug() << "测试参数 ratio:" << ratio;
        } else {
            qDebug() << "警告：testCases.json 文件不存在，使用默认 ratio 值:" << ratio;
        }

        // 4. 调用 CalculateItem_14 方法前的状态
        qDebug() << "调用CalculateItem_14前的processor状态:";
        qDebug() << "  hProcessSet.size():" << schProcessPosition.ProcessPosition.hProcessSet.size();
        qDebug() << "  sPositionsScore.size():" << schProcessPosition.ProcessPosition.sPositionsScore.size();
        qDebug() << "  hScoreByProcess.size():" << schProcessPosition.ProcessPosition.hScoreByProcess.size();

        // 5. 调用 CalculateItem_14 方法
        qDebug() << "调用 CalculateItem_14 方法，参数 ratio=" << ratio;
        try {
            schProcessPosition.CalculateItem_14(static_cast<float>(ratio));
            qDebug() << "CalculateItem_14 方法执行完成";
        } catch (const std::exception& e) {
            qWarning() << "CalculateItem_14 执行异常:" << e.what();
            throw;
        } catch (...) {
            qWarning() << "CalculateItem_14 执行未知异常";
            throw;
        }

        // 6. 调用 CalculateItem_14 后的状态
        qDebug() << "调用CalculateItem_14后的processor状态:";
        qDebug() << "  hProcessSet.size():" << schProcessPosition.ProcessPosition.hProcessSet.size();
        qDebug() << "  sPositionsScore.size():" << schProcessPosition.ProcessPosition.sPositionsScore.size();
        qDebug() << "  hScoreByProcess.size():" << schProcessPosition.ProcessPosition.hScoreByProcess.size();

        // 7. 写入结果文件
        createFileRecursion(resultFileName);
        QFile resultFile(resultFileName);
        if (resultFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream stream(&resultFile);
            
            // 输出处理后的分数信息
            // 遍历 hScoreByProcess 输出结果（按键排序）
            const QHash<qlonglong, QVector<SSCORE*>>& scoreByProcess = schProcessPosition.getScoreByProcess();
            bool hasData = false;
            qDebug() << "scoreByProcess.size():" << scoreByProcess.size();
            
            // 获取所有键并排序
            QList<qlonglong> keys = scoreByProcess.keys();
            std::sort(keys.begin(), keys.end());
            
            // 按排序后的键顺序输出
            for (qlonglong processId : keys) {
                QVector<SSCORE*> scores = scoreByProcess[processId];
                
                stream << "Process ID: " << processId << "\n";
                qDebug() << "Process ID:" << processId << "Scores count:" << scores.size();
                
                for (SSCORE* score : scores) {
                    stream << "  Position ID: " << score->Position
                           << ", Total Score: " << QString::number(score->Total, 'f', 4)
                           << ", Score Item [15]: " << QString::number(score->ScoreItem[13], 'f', 4) << "\n";
                    hasData = true;
                    qDebug() << "  Position ID:" << score->Position 
                             << ", Total Score:" << QString::number(score->Total, 'f', 4)
                             << ", Score Item [15]:" << QString::number(score->ScoreItem[13], 'f', 4);
                }
            }
            
            if (!hasData) {
                stream << "无数据输出\n";
                qDebug() << "无数据输出";
            }
            
            resultFile.close();
            qDebug() << "结果写入:" << resultFileName;
        }

    } catch (const std::exception& e) {
        qWarning() << "测试用例执行失败:" << e.what();
        // 写入错误结果
        createFileRecursion(resultFileName);
        QFile resultFile(resultFileName);
        if (resultFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream stream(&resultFile);
            stream << "测试失败: " << e.what() << "\n";
            resultFile.close();
        }
    }
}

void CalculateItem14TestJson::testCalculateItem14FromJson()
{
    qDebug() << "=== 开始使用JSON数据测试 CalculateItem_14 方法 ===";

    // 遍历测试用例
    for (int i = 1; i <= 52; i++) {
        try {
            QString folderPath;
            QString resultFileName;

            if (i <= 50) {
                folderPath = testDataFileBase + QString("calculateItem_14/random_case_%1/").arg(i);
                resultFileName = testResultFileBase + QString("calculateItem_14_c/random_case_%1.txt").arg(i);
            } else {
                folderPath = testDataFileBase + QString("calculateItem_14/manual_case_%1/").arg(i - 50);
                resultFileName = testResultFileBase + QString("calculateItem_14_c/manual_case_%1.txt").arg(i - 50);
            }

            QDir folder(folderPath);
            if (!folder.exists()) {
                qWarning() << "文件夹不存在：" << folderPath;
                continue;
            }

            qDebug() << "\n=== 处理测试用例" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50)) << "===";

            // 测试单个用例
            testSingleCase(folderPath, resultFileName);

            qDebug() << "测试完成:" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50));

        } catch (const std::exception& e) {
            qWarning() << "测试失败:" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50)) << "错误:" << e.what();
        }
    }
}

void CalculateItem14TestJson::cleanupTestCase()
{
    qDebug() << "清理 CalculateItem_14 JSON测试用例...";
}
